﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace WC
{
    namespace Pilot
    {
        class EchoServer
        {
            private const int _keepalive_interval = (30 * 1000);
            protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            protected WC.Net.Acceptor _acceptor = new WC.Net.Acceptor();
            Timer _timer;
            protected System.Collections.SortedList _commands = new System.Collections.SortedList();

            protected EchoServer()
            {
            }

            public bool Start(int port)
            {
                _acceptor.OnAccepted += OnAccepted;
                _acceptor.Start(port);

                //>>_timer = new Timer(new TimerCallback(OnTimer), null, _keepalive_interval, _keepalive_interval);
                WC.Utils.GCEnv.SetToForceGC(_keepalive_interval, _keepalive_interval);

                return true;
            }

            public void Stop()
            {
                _timer.Change(Timeout.Infinite, Timeout.Infinite);
            }

            private void OnTimer(Object state)
            {
                SendKeepAliveMessage();
            }

            protected void OnAccepted(Object sender, Object newlink)
            {
                WC.Net.Link link = (WC.Net.Link)newlink;
                link.OnReceived += OnReceived;
                link.OnSent += OnSent;
                link.OnClosed += OnClosed;

                //WC.Net.Acceptor acceptor = (WC.Net.Acceptor)sender;
                log.DebugFormat("link.InstanceID = {0}", link.InstanceID);
            }

            protected void OnReceived(Object sender, byte[] buffer, int size)
            {
                WC.Net.Link link = (WC.Net.Link)sender;
                //link.Stream.Write(buffer, 0, size);
                log.DebugFormat("{0} bytes, _stream.Length: {1}", size, link.Stream.Length);

                link.Send(buffer, size, this);
            }
            protected void OnSent(Object sender, byte[] buffer, int size, Object state)
            {
                log.DebugFormat("{0} bytes", size);
            }

            protected void OnClosed(Object sender)
            {
                WC.Net.Link link = (WC.Net.Link)sender;
                log.InfoFormat("[{0}] OnClosed(..)", link.InstanceID);
            }

            public void Print()
            {
                WC.Pattern.Singleton<WC.Net.NetStatistics>.Instance.Print(log);
                log.WarnFormat("[{0}] _acceptor.Links.Count = {1}", "^^", _acceptor.Links.Count);
            }

            public void SendKeepAliveMessage()
            {
                Echo.Ping.Builder builder = Echo.Ping.CreateBuilder();
                builder.Timestamp = DateTime.Now.Ticks;
                byte[] buffer = builder.Build().ToByteArray();

                _acceptor.Links.SendAll(buffer, buffer.Length);
            }
        }
    }
}
